* Oldalbum

If you have some old image archives from the web's baby years in the 90-ies and would like to link to the images from social media and have the linked images show up nicely, then this is the application you have waited for.

The application can be run in two ways:
 1. With a PostgreSQL database
 2. With an in-memory derby database that is provisioned from a file loaded from an URL (you need a web server that can serve the file)

The application doesn't store the images.  You need to let the original image archive to keep running.  The application just points into the old image archive and serve up the images with open graph and twitter card meta tags added.

The images are served up in a bootstrap styled, responsive layout, and should appear nicely on both mobile devices and larger screens.

** The reason this application exists
 The idea for the application comes from that I have some old albums from the 90ies that I occasionally would like to link to.  Since the images lack [[https://ogp.me][Open Graph]] or [[https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/abouts-cards][twitter card]] tags, linking to the images from social media doesn't look to hot.

 I first thought about changing the perl script that generates the albums, to add a wrapper to the main jpeg, with the OpenGraph headers.

 But then the thought struck me: I could just leave the old JPEGs where they are and create a completely separate webapp that provides a navigation and metadata framework and just uses an <img> tag to display the images from the location where they are today.

 And this is the webapp, called "oldalbum", because it is more a way to display existing old albums than yet another album application

** Titles, dates and sorting

For a logged in user, it is possible to add titles, descriptions and dates of images, or change the ones that were set during import.

If JPEG image is downloaded or if an album is downloaded as a zip file, the images will have the metadata set in their EXIF tags.

** Status

[[https://github.com/steinarb/oldalbum/actions/workflows/oldalbum-maven-ci-build.yml][file:https://github.com/steinarb/oldalbum/actions/workflows/oldalbum-maven-ci-build.yml/badge.svg]]
[[https://coveralls.io/github/steinarb/oldalbum][file:https://coveralls.io/repos/github/steinarb/oldalbum/badge.svg]]
[[https://sonarcloud.io/summary/new_code?id=steinarb_oldalbum][file:https://sonarcloud.io/api/project_badges/measure?project=steinarb_oldalbum&metric=alert_status#.svg]]
[[https://maven-badges.herokuapp.com/maven-central/no.priv.bang.oldalbum/oldalbum][file:https://maven-badges.herokuapp.com/maven-central/no.priv.bang.oldalbum/oldalbum/badge.svg]]
[[https://www.javadoc.io/doc/no.priv.bang.oldalbum/oldalbum][file:https://www.javadoc.io/badge/no.priv.bang.oldalbum/oldalbum.svg]]

[[https://sonarcloud.io/summary/new_code?id=steinarb_oldalbum][file:https://sonarcloud.io/images/project_badges/sonarcloud-white.svg]]

[[https://sonarcloud.io/summary/new_code?id=steinarb_oldalbum][file:https://sonarcloud.io/api/project_badges/measure?project=steinarb_oldalbum&metric=sqale_index#.svg]]
[[https://sonarcloud.io/summary/new_code?id=steinarb_oldalbum][file:https://sonarcloud.io/api/project_badges/measure?project=steinarb_oldalbum&metric=coverage#.svg]]
[[https://sonarcloud.io/summary/new_code?id=steinarb_oldalbum][file:https://sonarcloud.io/api/project_badges/measure?project=steinarb_oldalbum&metric=ncloc#.svg]]
[[https://sonarcloud.io/summary/new_code?id=steinarb_oldalbum][file:https://sonarcloud.io/api/project_badges/measure?project=steinarb_oldalbum&metric=code_smells#.svg]]
[[https://sonarcloud.io/summary/new_code?id=steinarb_oldalbum][file:https://sonarcloud.io/api/project_badges/measure?project=steinarb_oldalbum&metric=sqale_rating#.svg]]
[[https://sonarcloud.io/summary/new_code?id=steinarb_oldalbum][file:https://sonarcloud.io/api/project_badges/measure?project=steinarb_oldalbum&metric=security_rating#.svg]]
[[https://sonarcloud.io/summary/new_code?id=steinarb_oldalbum][file:https://sonarcloud.io/api/project_badges/measure?project=steinarb_oldalbum&metric=bugs#.svg]]
[[https://sonarcloud.io/summary/new_code?id=steinarb_oldalbum][file:https://sonarcloud.io/api/project_badges/measure?project=steinarb_oldalbum&metric=vulnerabilities#.svg]]
[[https://sonarcloud.io/summary/new_code?id=steinarb_oldalbum][file:https://sonarcloud.io/api/project_badges/measure?project=steinarb_oldalbum&metric=duplicated_lines_density#.svg]]
[[https://sonarcloud.io/summary/new_code?id=steinarb_oldalbum][file:https://sonarcloud.io/api/project_badges/measure?project=steinarb_oldalbum&metric=reliability_rating#.svg]]

*** Release history

| Date                   | Version | Description                                                                                                    |
|------------------------+---------+----------------------------------------------------------------------------------------------------------------|
| <2025-06-14 Sat 20:14> |   2.2.5 | Built for java 21, postgresql 42.7.7, authservice 3.0.0                                                        |
| <2025-05-17 Sat 15:18> |   2.2.4 | Add support for karaf config of shiro rememberme session timeout                                               |
| <2025-05-05 Mon 19:16> |   2.2.3 | Fixes NPE in zip file download, uses jersey 2.46 and jackson 2.19.0                                            |
| <2025-04-24 Thu 18:43> |   2.2.2 | Fixes reload after changing access, fixes URL sharing, fixes shiro rememberme, uses shiro 2.0.4                |
| <2025-04-05 Sat 19:13> |   2.2.1 | Use liquibase 4.31.1                                                                                           |
| <2025-03-02 Sun 19:11> |   2.2.0 | Use runtime-incompatible bang-servlet 2.0.0, authservice 2.1.0                                                 |
| <2025-02-19 Wed 22:17> |   2.1.8 | Use liquibase 4.31.0                                                                                           |
| <2025-02-18 Tue 22:22> |   2.1.7 | Bugfix: stop album from showing up empty in the react app                                                      |
| <2025-02-12 Wed 19:22> |   2.1.6 | Replace axios/saga with RTK query, lock accounts on repeated logn failures, postgresql 42.7.5                  |
| <2024-12-14 Sat 07:40> |   2.1.5 | Use liquibase 4.30.0, postgresql jdbc 42.7.4, shiro 2.0.2, bang-servlet 1.8.1 and authservice 2.0.4            |
| <2024-11-06 Wed 17:47> |   2.1.4 | Use TwelveMonkeys 3.12.0, replace webpack with vite for frontend build                                         |
| <2024-10-02 Wed 00:08> |   2.1.3 | With a working robots.txt limiting oldalbum traffic                                                            |
| <2024-08-03 Sat 10:14> |   2.1.2 | Use jersey 2.33, jackson 2.17.2, improved 404 non-JavaScript up-link                                           |
| <2024-08-01 Thu 17:01> |   2.1.1 | Use liquibase 4.29.0, add cancel button to login and get 404 response for non-JavaScript                       |
| <2024-07-28 Sun 21:48> |   2.1.0 | Render on browsers without JavaScript (tested on dillo 3.1.0)                                                  |
| <2024-07-05 Fri 20:18> |   2.0.1 | Use liquibase 4.28.0                                                                                           |
| <2024-05-31 Fri 21:42> |   2.0.0 | Use shiro 2.0.1 and new record-based API of the UserService OSGi service                                       |
| <2024-04-06 Sat 13:30> |  1.9.28 | Use liquibase 4.27.0 and build with node.js 20.12.0 and karaf 4.4.5                                            |
| <2024-03-25 Mon 20:13> |  1.9.27 | Possible to unprotect protected pictures when sharing them, dynamic shiro protection of albums and pictures    |
| <2024-03-02 Sat 11:33> |  1.9.26 | Use postgresql jdbc 42.7.2                                                                                     |
| <2024-02-12 Mon 23:05> |  1.9.25 | Fix 404 Not Found after login from edit page, many layout improvements                                         |
| <2024-01-18 Thu 23:59> |  1.9.24 | Many layout fixes, better import of nginx directory listings into albums                                       |
| <2024-01-04 Thu 13:00> |  1.9.23 | Improved UI layout, fixed bug button not appearing, fixed year of album consisting of albums                   |
| <2023-12-27 Wed 16:30> |  1.9.22 | Layout improvements, select images for download, group albums on year                                          |
| <2023-12-14 Thu 20:22> |  1.9.21 | Use shiro 1.13.0, make navbar dropdown and download buttons look and feel better                               |
| <2023-12-12 Tue 19:36> |  1.9.20 | Use liquibase 4.24.0, move dowload buttons out of navbar dropdowns                                             |
| <2023-11-15 Wed 16:37> |  1.9.19 | Use JAX-RS streaming when downloading images and zip files, fix NPEs from missing metadata                     |
| <2023-11-07 Tue 23:11> |  1.9.18 | Make EXIF metadata replacment in downloads work (using TwelveMonkeys 3.10.1)                                   |
| <2023-11-05 Sun 15:03> |  1.9.17 | Use jersey 2.41, jackson 2.15.3, pax-jdbc 1.5.6, junit jupiter 5.10.0, mockito 5.7.0, and mockrunner 2.0.7     |
| <2023-10-31 Tue 21:45> |  1.9.16 | Add download of images and albums, EXIF metadata support on import and download                                |
| <2023-07-30 Sun 14:50> |  1.9.15 | Use jersey 2.40 and jackson 2.15.2                                                                             |
| <2023-07-14 Fri 14:46> |  1.9.14 | Mistaken unneccessary release for Java 17                                                                      |
| <2023-07-08 Sat 23:53> |  1.9.13 | Use java 17                                                                                                    |
| <2023-07-02 Sun 20:55> |  1.9.12 | Use liquibase 4.23.0                                                                                           |
| <2023-06-06 Tue 21:08> |  1.9.11 | Use authservice 1.15.7 and shiro 1.11.0                                                                        |
| <2023-04-26 Wed 23:18> |  1.9.10 | Use jersey-karaf-feature 1.9.5, jackson 2.15.0                                                                 |
| <2023-04-24 Mon 21:34> |   1.9.9 | Use jersey-karaf-feature 1.9.4, jersey 2.39.1, jackson 2.14.2                                                  |
| <2023-04-23 Sun 14:07> |   1.9.8 | Avoid caching of the webapp frontend                                                                           |
| <2023-03-06 Mon 22:29> |   1.9.7 | Use liquibase 4.19.0, pax-jdbc 1.5.5, postgresql jdbc 42.5.4, karaf 4.4.3                                      |
| <2023-01-20 Fri 23:51> |   1.9.6 | Add sort-by-date functionality, improved navigation, improved 404 and 403 responses                            |
| <2022-12-10 Sat 16:35> |   1.9.5 | Upgrade authservice to 1.15.1, because the BOM of 1.15.0 was broken                                            |
| <2022-12-07 Wed 22:42> |   1.9.4 | Revert the reduction of col width for album entries on large displays                                          |
| <2022-12-06 Tue 18:50> |   1.9.3 | Fix wrong redirect after login, reduce col width for album entries on large displays                           |
| <2022-12-05 Mon 17:50> |   1.9.2 | Remove unneeded scrollbars, redirect to protected url after login, use jersey 2.37 and jackson 2.14.1          |
| <2022-11-26 Sat 12:36> |   1.9.1 | Better picture scaling on large displays, use postgresql jdbc 42.5.1, use jsoup 1.15.3                         |
| <2022-11-24 Thu 22:58> |   1.9.0 | Password protected access to albums and pictures, batch import of albums/pictures                              |
| <2022-11-01 Tue 21:46> |   1.8.6 | Use liquibase 4.17.1, postgresql jdbc driver 42.4.1 and upgrade of all upgradable frontend packages            |
| <2022-08-21 Sun 11:24> |   1.8.5 | Use liquibase 4.15.0                                                                                           |
| <2022-08-10 Wed 22:38> |   1.8.4 | Use servlet 1.6.2, maven-bundle-plugin 5.1.8, jsoup 1.15.2, junit jupiter 5.9.0, mockito 4.6.1, assertj 2.23.1 |
| <2022-08-10 Wed 08:33> |   1.8.3 | Use jersey 2.36 and postgresql jdbc driver 42.4.1                                                              |
| <2022-07-25 Mon 19:11> |   1.8.2 | Use karaf 4.4.1                                                                                                |
| <2022-06-01 Wed 19:21> |   1.8.1 | Use jackson 2.13.3                                                                                             |
| <2022-05-29 Sun 14:43> |   1.8.0 | Use karaf 4.4.0 and OSGi 8, use redux hooks in the frontend                                                    |
| <2022-02-21 Mon 18:56> |  1.7.12 | Use java 11, karaf 4.3.6, postgresql JDBC 42.3.3, jersey 2.35, jackson 2.13.1, and node.js 16.14.0             |
| <2021-10-14 Thu 21:40> |  1.7.11 | Use karaf 4.3.3, postgresql JDBC 4.2.24, and authservice 1.3.11                                                |
| <2021-10-01 Fri 00:12> |  1.7.10 | Use jsoup 1.14.3 and axios 0.21.4                                                                              |
| <2021-07-26 Mon 16:47> |   1.7.9 | Expand pictures to fill entire screen when tilting mobile to landscape                                         |
| <2021-07-25 Sun 23:37> |   1.7.8 | Use PostgreSQL JDBC driver 42.2.23                                                                             |
| <2021-06-16 Wed 00:17> |   1.7.7 | Use jersey 2.34 and jackson 12.3                                                                               |
| <2021-06-13 Sun 16:14> |   1.7.6 | Align dependency versions with other applications                                                              |
| <2021-06-01 Tue 20:15> |   1.7.5 | Get OSGi 7 framework and OSGi 7 compendium versions from the karaf BoM                                         |
| <2021-05-24 Mon 19:15> |   1.7.4 | use eslint in frontend, upgrade npm dependecies and webpack, OSGi 7 web whiteboard                             |
| <2021-05-02 Sun 20:14> |   1.7.3 | servlet 1.5.4, bootstrap 4.6.0, node.js 14.16.1                                                                |
| <2021-04-19 Mon 22:26> |   1.7.2 | Get maven dependency versions from Bill of Material poms                                                       |
| <2021-04-17 Sat 10:57> |   1.7.1 | Get maven dependency versions and maven plugin config from paren POM                                           |
| <2021-04-12 Mon 23:52> |   1.7.0 | Built with karaf 4.3.0 and OSGi 7                                                                              |
| <2021-03-21 Sun 15:37> |   1.6.6 | Get maven dependencies from the karaf 4.2.11 BoM                                                               |
| <2021-03-17 Wed 23:52> |   1.6.5 | Use builder pattern to create beans used by the REST APIs                                                      |
| <2021-02-18 Thu 21:22> |   1.6.4 | Fix loading issues caused by leftover old style karaf repository URLs                                          |
| <2021-01-25 Mon 23:59> |   1.6.3 | Use jersey 2.33, JerseyServlet 1.4.0, authservice 1.12.1 and jackson 2.12.1, no functional changes             |
| <2021-01-19 Tue 23:28> |   1.6.2 | Use shiro 1.7.0 and authservice 1.12.0, no functional changes                                                  |
| <2021-01-17 Sun 20:26> |   1.6.1 | Use axios 0.21.1 to fix github security alert. New karaf feature URL                                           |
| <2020-11-07 Sat 17:18> |   1.6.0 | Preview when adding imageUrl, load metadata when image loads, fix add picture/album cancel button              |
| <2020-10-31 Sat 20:52> |   1.5.0 | Use image as thumbnail, when no thumbnail exists, add share link button                                        |
| <2020-10-10 Sat 12:54> |   1.4.2 | Use PostgreSQL 42.2.17 where [[https://github.com/pgjdbc/pgjdbc/issues/1891][the karaf feature issue]] is fixed                                                  |
| <2020-09-26 Sat 12:33> |   1.4.1 | Downgrade PostgreSQL JDBC driver to 42.2.12 because of karaf feature issue                                     |
| <2020-09-23 Wed 23:05> |   1.4.0 | Added swipe between pictures, added environment variables for docker image config                              |
| <2020-09-13 Sun 23:11> |   1.3.0 | More large display improvements, webcrawler friendly title/description, docker image                           |
| <2020-09-01 Tue 22:03> |   1.2.0 | Improved layout on large display. REST endpoint for dumping database                                           |
| <2020-08-26 Wed 23:41> |   1.1.0 | Make page preview work in twitter, show prev/next arrows better on large displays                              |
| <2020-08-23 Sun 00:29> |   1.0.0 | First release                                                                                                  |

** Installation

*** Installation with test database
 Procedure:
  1. [[https://karaf.apache.org/manual/latest/quick-start.html][Download and install apache karaf]] (download the karaf binary tar-ball or .zip file, unpack, and start with "./bin/karaf" in a terminal window)
  2. Clone and build oldalbum
     #+begin_example
       git clone https://github.com/steinarb/oldalbum.git
       cd oldalbum
       mvn install
     #+end_example
  3. From the karaf console (i.e. the terminal window where you started karaf), give the following commands:
     #+BEGIN_EXAMPLE
       feature:repo-add mvn:no.priv.bang.oldalbum/karaf/LATEST/xml/features
       feature:install oldalbum-with-derby
     #+END_EXAMPLE
  4. Visit http://localhost:8181/oldalbum in a web browser
  5. Open the menu from the button with three lines on top right and log in with username admin, password admin, this will give you access to edit facilities

*** Installation with production database
 Procedure:
  1. Download and install apache karaf
  2. Create PosgreSQL user karaf, and give "karaf" (without the quotes) as the password (or pick a different password, and change the database password in the karaf config file =etc/org.ops4j.datasource-oldalbum-production.cfg=, note1: this is =etc/= inside karaf note2: the file is created after oldalbum installation, and you will have to restart karaf after changing the config file):
     #+begin_example
       /usr/bin/sudo -u postgres createuser karaf --pwprompt
     #+end_example
  3. Create a blank PostgreSQL database with user karaf as the owner
     #+begin_example
       /usr/bin/sudo -u postgres createdb -O karaf oldalbum
     #+end_example
  4. From the karaf console, give the following commands:
     #+BEGIN_EXAMPLE
       feature:repo-add mvn:no.priv.bang.authservice/karaf/LATEST/xml/features
       feature:install user-admin-with-productiondb
       feature:repo-add mvn:no.priv.bang.oldalbum/karaf/LATEST/xml/features
       feature:install oldalbum-with-postgresql-and-provided-authservice
     #+END_EXAMPLE

*** Installation with in-memory database initialized from URL

Procedure:
 1. Set the environment variable DATABASE_CONTENT_URL pointing to the raw content of a [[https://gist.github.com/steinarb/dba5f579774d04e69f3073d029622027][github gist containing a liquibase changeset setting up just an empty root album]] :
    #+begin_example
      export DATABASE_CONTENT_URL=https://git.io/JUnF4
    #+end_example
 2. Start karaf from the shell where you've set the DATABASE_CONTENT_URL environment variable
 3. Install the oldalbum application :
    #+begin_example
      feature:repo-add mvn:no.priv.bang.oldalbum/karaf/LATEST/xml/features
      feature:install oldalbum-with-memory-db-with-url-init
    #+end_example
 4. Visit http://localhost:8181/oldalbum in a web browser:
    1. Log in with username "admin" (without the quotes) and password "admin" (also without the quotes)
    2. Add the albums and images you want to display
 5. When you're happy with the album contents, download http://localhost:8181/oldalbum/api/dumproutessql and put the results in a place that can be reached with a HTTP URL from where you start your production karaf instance, e.g. as a github gist
 6. Set the environment variable DATABASE_CONTENT_URL to the raw content of your github gist in the shell where you'll start the karaf hosting your production oldalbum instance

*** Installation using docker image

Procedure:
 1. Pull the latest version of the image from docker hub
    #+begin_example
      docker pull steinarb/oldalbum:latest
    #+end_example
    (/Note/! The image provisions the latest released version of oldalbum from maven central on startup, so there is no need to get a new version of the image to get a new oldalbum release. A stop and start of the image will be sufficient)
 2. Start the docker image with a minimal database that only contains the top album
    #+begin_example
      docker run -p 8101:8101 -p 8181:8181  -e "DATABASE_CONTENT_URL=https://git.io/JUnF4" -d steinarb/oldalbum:latest
    #+end_example
 3. Visit http://localhost:8181/oldalbum in a web browser:
    1. Log in with username "admin" (without the quotes) and password "admin" (also without the quotes)
    2. Add the albums and images you want to display:
       1. To add an album:
          1. Click on the button "Add album"
          2. At least add a unique local path for the album (the album will become a child of the album you clicked "Add album" in)
          3. Optionally add a title and a description
          4. Click on the "Add" button to add the new album
       2. To add a picture:
          1. Navigate to the album you want to add a picture to
          2. Click on the button "Add picture"
          3. At least provide the URL of the image you wish to add (the filename without extension will become the suggested local path)
          4. Optionally add a the URL of a thumbnail (if you don't have a thumbnail, just leave this field open and a scaled down version of the image itself will be used as the thumbnail)
          5. Optionally add a title and a description
          6. Click on the button "Add" to add the image to the album
       3. Pictures and albums will be displayed in the order they are added
       4. Click on the arrows to move a picture or album up or down
 4. When you're happy with the album contents, download http://localhost:8181/oldalbum/api/dumproutessql and put the results in a place that can be reached with a HTTP URL from where you start your production karaf instance, e.g. as a github gist
 5. Stop the image and restart it, this time with a DATABASE_CONTENT_URL pointing to a web server serving up the dumped file (as e.g. with this github gist):
    #+begin_example
      docker run -p 8101:8101 -p 8181:8181  -e "DATABASE_CONTENT_URL=https://gist.githubusercontent.com/steinarb/8a1de4e37f82d4d5eeb97778b0c8d459/raw/6cddf18f12e98d704e85af6264d81867f68a097c/dumproutes.sql" -d steinarb/oldalbum:latest
    #+end_example

**** Set admin user username and password when using docker

If you want to change the username and/or password of the admin user, it can be done by setting the environment variables USERNAME and PASSWORD, e.g. like so:
#+begin_example
  docker run -p 8101:8101 -p 8181:8181  -e "DATABASE_CONTENT_URL=https://git.io/JUnF4" -e "USERNAME=album" -e "PASSWORD=zekret" -d steinarb/oldalbum:latest
#+end_example


**** Read-only installation using docker

If you want your album to be read-only, it's possible to disable the login and the edit functionality by setting the environmentvariable ALLOW_MODIFY, e.g. like so:
#+begin_example
  docker run -p 8101:8101 -p 8181:8181  -e "ALLOW_MODIFY=false" -e "DATABASE_CONTENT_URL=https://gist.githubusercontent.com/steinarb/8a1de4e37f82d4d5eeb97778b0c8d459/raw/6cddf18f12e98d704e85af6264d81867f68a097c/dumproutes.sql" -d steinarb/oldalbum:latest
#+end_example

** Non-JavaScript version
The oldalbum website is a [[https://react.dev][react.js]] webapp.

Prior to version 2.1.0, what met browsers without JavaScript when opening https://oldalbum.bang.priv.no was the text
#+begin_example
  This webpage requires javascript in the browser!
#+end_example

Since one reason for creating oldalbum in the first place, was to have shareable URLs with OpenGraph headers, it has felt a little off not to have that URL part of a web site that can be crawled and walked to see the pictures.

So the plan was to at least have a simple server side rendered web page that linked albums and pictures in the same way as the react.js webapp.

And then earlier in 2024, [[https://dillo-browser.github.io/dillo.org.html][the dillo browser was resurrected]] and [[https://dillo-browser.github.io/release/3.1.0/][dillo 3.1.0 was released]] and provided a graphical browser with CSS support but no javascript and the decision was made to target dillo 3.1.0 and what it currently supports of CSS.

What's supported in the non-JavaScript version, is:
 1. Navigation through albums and pictures
 2. Shareable URLs with OpenGraph metadata
 3. Download links for albums and pictures
 4. The possibility to log in to see protected pictures and albums (requires cookies to be enabled in dillo, cookies are disabled by default i cookies)

What is in the react.js version and not supported in the non-JavaScript version is edit functionality:
 1. No functionality to add albums and pictures
 2. No functionality to delete albums and pictures
 3. No functionality to edit picture metadata
 4. No functionality to modify album sort order

For this one needs now (and in the foreseeable future) a browser that can run react.js.

** License

This software is licensed under Apache Public License v 2.0.

See the LICENSE file for the full details.
